package edu.mse.camel.client.uml.collab.actions;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorActionDelegate;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IViewActionDelegate;
import org.eclipse.ui.IViewPart;

import edu.mse.camel.client.core.events.model.BaselineResourceUpdate;
import edu.mse.camel.client.eventbus.pubsub.EventManager;
import edu.mse.camel.client.events.EventIDs;
import edu.mse.camel.client.events.peer.SendGenericPeerEvent;
import edu.mse.camel.client.log.Debug;
import edu.mse.camel.client.uml.collab.CollabPlugin;

public class TransferFileAction implements IViewActionDelegate, IEditorActionDelegate {
	IFile [] selectedFiles;
	
	@Override
	public void init(IViewPart view) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void run(IAction action) {
		MessageBox messageBox = new MessageBox(new Shell(), SWT.OK);
		messageBox.setText("Publish these files");
		String msg = new String();
		for ( IFile file: selectedFiles) {
			msg = msg + file.getName() + "; ";
		}
		messageBox.setMessage(msg);
		messageBox.open();

		if(selectedFiles.length == 0) {
			Debug.log_info(CollabPlugin.PLUGIN_ID, "TransferFile : file array is empty");
		}
		for ( IFile file: selectedFiles) {
			
			Debug.log_info(CollabPlugin.PLUGIN_ID, "TransferFile : processing file");
			
			// allocate 16MB buffer
			final int maxFileSize = 16*1024*1024;
			byte [] buf = new byte[maxFileSize];
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			int offset = 0;
			try {
				InputStream in = file.getContents();
				while(in.available()>0) {
						int len = in.read(buf);
						
						if(offset+ len >= maxFileSize) {
							throw new IOException("File size exceeds buffer limit");
						}
						
						out.write(buf, offset, len);
						offset += len;
				}
				
				SendGenericPeerEvent peer = new SendGenericPeerEvent();
				BaselineResourceUpdate update = new BaselineResourceUpdate();

				update.setOriginalFileName(file.getName());
				update.setOriginalProjectName(file.getProject().getName());
				
				update.setFileBuffer(out.toByteArray());
				peer.setSpecificEventId(EventIDs.BASELINE_RESOURCE_UPDATE_EVENT);
				peer.writeObject(update);
				EventManager.getInstance().dispatchEventAsynchronous(peer);

			} catch (CoreException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				
				MessageBox errorMsg = new MessageBox(new Shell(), SWT.OK);
				errorMsg.setText("Publish these files");
				errorMsg.setMessage("Error publishing : " + file.getName());
				errorMsg.open();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				
				MessageBox errorMsg = new MessageBox(new Shell(), SWT.OK);
				errorMsg.setText("Publish these files");
				errorMsg.setMessage("Error reading : " + file.getName());
				errorMsg.open();
			}
		}		
	}

	@SuppressWarnings("unchecked")
	@Override
	public void selectionChanged(IAction action, ISelection selection) {
		ArrayList<IFile> newFiles = new ArrayList<IFile>();
		IFile file = null;
		if ( selection != null && selection instanceof IStructuredSelection ) {
			IStructuredSelection ss = (IStructuredSelection) selection;
			Iterator iter = ss.iterator();
			
			if(!iter.hasNext()) {
				Debug.log_info(CollabPlugin.PLUGIN_ID, "selectionChanged : selection has no next element");
			}
			
			for ( ; iter.hasNext();) {
				Object obj = iter.next();
				
				if(obj instanceof IFile) {
					Debug.log_info(CollabPlugin.PLUGIN_ID, "selectionChanged : got a file");
					file = (IFile) obj;
				}
				else if ( obj instanceof IAdaptable){
					Debug.log_info(CollabPlugin.PLUGIN_ID, "selectionChanged : got an IAdaptable");
					
					IAdaptable a = (IAdaptable) obj;
					IResource res = (IResource) a.getAdapter(IResource.class);
					if ( res instanceof IFile) {
						file = (IFile) res;
						Debug.log_info(CollabPlugin.PLUGIN_ID, "selectionChanged : got an IAdaptable and it can be converted to an IFile");
					}
					else {
						Debug.log_info(CollabPlugin.PLUGIN_ID, "selectionChanged : got an IAdaptable but cann't be converted to an IFile");
					}
				}
				
				if(file != null ) {
					// the eclipse book example has this query, but it seems no file is synced ??
					//if(!file.isSynchronized(IResource.DEPTH_ZERO)) {
						newFiles.add(file);
						Debug.log_info(CollabPlugin.PLUGIN_ID, "selectionChanged : add to newFiles");
					//}
				}
			}
			
		}
		else {
			Debug.log_info(CollabPlugin.PLUGIN_ID, "selectionChanged : null(selection) or not_instance_of(selection, IStructuredSelection)");
		}
		
		if ( newFiles.isEmpty()) {
			selectedFiles = null;
			action.setEnabled(false);
			Debug.log_info(CollabPlugin.PLUGIN_ID, "selectionChanged : newFile is empty");
		}
		else {
			selectedFiles = (IFile[]) newFiles.toArray(new IFile[newFiles.size()]);
			action.setEnabled(true);
			Debug.log_info(CollabPlugin.PLUGIN_ID, "selectionChanged : newFile is not empty");
		}
		
	}

	@Override
	public void setActiveEditor(IAction action, IEditorPart targetEditor) {
		// TODO Auto-generated method stub
		
	}

}
